﻿namespace StockSharp.Algo.Indicators.Williams
{
	using StockSharp.Algo.Indicators.Misc;
	using StockSharp.Algo.Indicators.Trend;

	/// <summary>
	/// Реализация одной из линий индикатора Alligator (Jaw, Teeth, Lips).
	/// </summary>
	public class AlligatorLine : LengthIndicator<decimal>
	{
		private readonly MedianPrice _medianPrice;

		private readonly SmoothedMovingAverage _sma;
		//private readonly SimpleMovingAverage _sma;

		/// <summary>
		/// Создать <see cref="AlligatorLine"/>.
		/// </summary>
		public AlligatorLine()
		{
			_medianPrice = new MedianPrice();
			_sma = new SmoothedMovingAverage();
			//_sma = new SimpleMovingAverage();
		}

		/// <summary>
		/// Длина периода.
		/// </summary>
		public override int Length
		{
			get
			{
				return _sma.Length;
			}
			set
			{
				_sma.Length = value;
				Reset();
			}
		}

		private int _shift;

		/// <summary>
		/// Сдвиг в будущее.
		/// </summary>
		public int Shift
		{
			get { return _shift; }
			set
			{
				_shift = value;
				Reset();
			}
		}

		/// <summary>
		/// Сбросить состояние индикатора на первоначальное. Метод вызывается каждый раз, когда меняются первоначальные настройки (например, длина периода).
		/// </summary>
		public override void Reset()
		{
			_sma.Reset();
			_medianPrice.Reset();
			base.Reset();
		}

		/// <summary>
		/// Сформирован ли индикатор.
		/// </summary>
		public override bool IsFormed { get { return Buffer.Count > Shift; } }

		/// <summary>
		/// Возможно ли обработать входное значение.
		/// </summary>
		/// <param name="input">Входное значение.</param>
		/// <returns>True, если возможно, иначе, false.</returns>
		public override bool CanProcess(IIndicatorValue input)
		{
			return _medianPrice.CanProcess(input);
		}

		/// <summary>
		/// Обработать входное значение.
		/// </summary>
		/// <param name="input">Входное значение.</param>
		/// <returns>Результирующее значение.</returns>
		protected override decimal OnProcess(IIndicatorValue input)
		{
			//если кол-во в буфере больше Shift, то первое значение отдали в прошлый раз, удалим его.
			if (Buffer.Count > Shift)
				Buffer.RemoveAt(0);

			var smaResult = _sma.Process(_medianPrice.Process(input));
 			if (_sma.IsFormed)
				Buffer.Add(smaResult.GetValue<decimal>());

			return Buffer.Count > Shift ? Buffer[0] : this.GetCurrentValue();
		}

		/// <summary>
		/// Создать копию данного объекта.
		/// </summary>
		/// <returns>Копия данного объекта.</returns>
		public override IIndicator Clone()
		{
			return new AlligatorLine {Length = Length, Shift = Shift, Name = Name};
		}
	}
}